package jsonparser;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by pendragon on 17-5-20.
 */
public class JSONObject {
    private StringBuilder sb;

    private Map<String, Object> valueMap;

    public JSONObject() {
        valueMap = new LinkedHashMap<>();
    }

    public void putString(String key, String value) {
        valueMap.put(key, value);
    }

    public void putBoolean(String key, boolean value) {
        valueMap.put(key, value);
    }

    public void putNumber(String key, double value) {
        valueMap.put(key, value);
    }

    public void putJSONObject(String key, JSONObject object) {
        valueMap.put(key, object);
    }

    public void putJSONArray(String key, JSONArray array) {
        valueMap.put(key, array);
    }

    public void putNull(String key) {
        valueMap.put(key, null);
    }

    public Object getObject(String key){
        return valueMap.get(key);
    }

    public JSONObject getJSONObject(String key){
        Object o = getObject(key);
        if (o != null && o instanceof JSONObject)
            return (JSONObject) o;
        else
            return null;
    }

    public JSONArray getJSONArray(String key){
        Object o = getObject(key);
        if (o != null && o instanceof JSONArray)
            return (JSONArray) o;
        else
            return null;
    }

    public String getString(String key){
        Object o = getObject(key);
        if (o != null && o instanceof String)
            return (String) o;
        else
            return null;
    }

    public Boolean getBoolean(String key){
        Object o = getObject(key);
        if (o != null && o instanceof Boolean)
            return (Boolean) o;
        else
            return null;
    }

    public Number getNumber(String key){
        Object o = getObject(key);
        if (o != null && o instanceof Number)
            return (Number) o;
        else
            return null;
    }

    @Override
    public String toString() {
        format();
        return sb.toString();
    }

    protected void format(StringBuilder sb, int n){
        fillTab(sb, n);

        Iterator<Map.Entry<String, Object>> it = valueMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            sb.append('\n');
            fillTab(sb, n + 1);
            sb.append('"')
                    .append(entry.getKey())
                    .append('"')
                    .append(':');

            Object value = entry.getValue();

            if (value instanceof String){
                sb.append('"')
                        .append(entry.getValue())
                        .append('"');
            } else if (value instanceof JSONObject){
                sb.append('{');
                ((JSONObject)value).format(sb, n + 1);
            } else if (value instanceof JSONArray) {
                sb.append('[');
                ((JSONArray)value).format(sb, n + 1);
            } else {
                sb.append(entry.getValue());
            }

            sb.append(',');
        }

        sb.deleteCharAt(sb.length() - 1);
        sb.append('\n');
        fillTab(sb, n);
        sb.append('}');
    }

    private void format(){
        sb = new StringBuilder();
        sb.append('{');
        format(sb, 0);
    }

    private void fillTab(StringBuilder sb, int n){
        for (int i = 0; i < n; i++){
            sb.append('\t');
        }
    }

}
